package authuserpbkdf

import (
	"crypto/rand"
	"encoding/hex"
	"log"
	"strings"

	"gitee.com/tgodfather/utility/auth"

	"github.com/tjfoc/gmsm/sm3"
	"github.com/tjfoc/gmsm/sm4"
)

// save   	username	-  用户名
//
//	realPassword-  用户实际密码
//	sSalt 		-  保存时的随机数 32 位
//	savePassword	-  实际保存的密码
//			sHash  = sm3(username + hex2str(sSalt))  --产生32位 哈希值，取前16位作为密钥
//			savePassword =  hex2str(sSalt) + hex2str(sm4.enc(sHash[:16], realPassword))

// check	校验处理
//  1. 根据输入密码 提取 inSalt 与 加密后的密码 insPassword
//     insalt = password[:32]  insPassword=password[32:]
//  2. 从保存密码 提取  sSalt 与  加密后的密码  sPassword, 最终求得实际 realPassword
//     sSalt = sPassword[:32]  sPassword= str2Hex(savePassword[32:])
//     sHash = sm3(username + hex2str(sSalt))
//     realPassword = sm4.dec(sHash[:16], sPassword)
//  3. 检验密码是否一致
//     rPassword = pbkdf2(sha256, inSalt , realPassword)
//     if rPassword == insPassword
//     return true	//校验成功
//     else
//     return false
type UserStore struct {
	storeUsername string
	storePassword string
	//sSalt         []byte // 保存的salt ， sSalt=storePassword[:32]
	//sHash []byte // sm3(username + hex2str(sSalt))
	realPassword string
}

func (s *UserStore) Username() string {
	return s.storeUsername
}
func (s *UserStore) Password() string {
	return s.storePassword
}

func (s *UserStore) Verify(v auth.Validator) (rc bool, err error) {

	rc = false
	if sKey, err := v.GenerateKey(s.realPassword); err == nil {
		if strings.Compare(sKey, v.Key()) == 0 {
			rc = true
		}
	}
	return rc, err
}

func NewUserStore(Username, Password string, opt ...auth.StoreOption) auth.AuthStore {

	sUsername := Username
	sPassword := ""
	realPassword := ""
	opts := auth.NewStoreOptions(opt...)

	if opts.NeedGenerate { // 需要生成，通常应用于需要生成 存储密码的场景
		realPassword = Password
		sPass, err := genterateSavePassword(sUsername, realPassword)
		sPassword = sPass
		if err != nil {
			log.Println("---------------- genterateSavePassword error", sPassword, realPassword, err)
		}

	} else { //不需要生成密码，通常应用于从数据库load数据的场景
		sPassword = Password
		_, rPass, err := parseSavePassowrd(sUsername, sPassword)
		realPassword = rPass
		if err != nil {
			log.Println("---------------- parseSavePassowrd error", sPassword, realPassword, err)
		}
	}

	ps := &UserStore{
		storeUsername: sUsername,
		storePassword: sPassword,
		realPassword:  realPassword,
	}
	return ps
}

func genterateSavePassword(username string, realPass string) (sPass string, err error) {
	// 生成一个16字节的随机密钥
	salt := make([]byte, 16)
	if _, rErr := rand.Read(salt); rErr != nil {
		log.Println("Error generating random key:", err)
		return "", rErr
	}

	saltStr := hex.EncodeToString(salt)
	data := username + saltStr
	hash := sm3.Sm3Sum([]byte(data))
	// 创建一个新的SM4 Cipher实例  SM4加密长度
	// cipher, cErr := sm4.NewCipher(hash[:16]) // 取hash前16位作为cipher key
	// if cErr != nil {
	// 	log.Println("Error creating cipher:", err)
	// 	return "", cErr
	// }
	// 要实现

	// 密码进行加密
	// encPass, eErr := gaes.Encrypt([]byte(realPass), hash)
	// if eErr != nil {
	// 	// log.Println("Error gaes.Encrypt:", eErr)
	// 	return "", eErr
	// }

	// 密码进行加密
	// 设置SM4算法实现的IV值,不设置则使用默认值
	encPass, err := sm4.Sm4Ecb(hash[:16], []byte(realPass), true) //sm4Ecb模式pksc7填充加密
	if err != nil {
		log.Println("sm4 enc error: ", err)
		return
	}

	// encPass := make([]byte, len(realPass))
	// cipher.Encrypt(encPass, []byte(realPass))
	// log.Printf("---------------------Encrypted Message: %s\n", hex.EncodeToString(encPass))

	sPass = saltStr + hex.EncodeToString(encPass)
	return sPass, nil
}

func parseSavePassowrd(sUsername string, sPassword string) (saltStr string, realPass string, err error) {
	// log.Println("---------------------parseSavePassowrd", sUsername, sPassword)
	if len(sPassword) <= 32 {
		return "", "", auth.ErrInvalidPasswordLength
	}

	saltStr = sPassword[:32]

	passStr := sPassword[32:]
	encPass, dErr := hex.DecodeString(passStr)
	if dErr != nil {
		return "", "", dErr
	}

	data := sUsername + saltStr
	hash := sm3.Sm3Sum([]byte(data))

	// // 创建一个新的SM4 Cipher实例
	// cipher, cErr := sm4.NewCipher(hash[:16]) // 取hash前16位作为cipher key
	// if cErr != nil {
	// 	// fmt.Println("Error creating cipher:", err)
	// 	return "", "", cErr
	// }

	// //解密密码
	// decryptedMessage := make([]byte, len(encPass))
	// cipher.Decrypt(decryptedMessage, encPass)

	// realPass = string(decryptedMessage)

	//解密密码
	// real, cErr := gaes.Decrypt(encPass, hash)
	// if cErr != nil {
	// 	// log.Println("gaes.Decrypt error", dErr, hash)
	// 	return "", "", cErr
	// }
	real, cErr := sm4.Sm4Ecb(hash[:16], encPass, false) //sm4Ecb模式pksc7填充解密
	if cErr != nil {
		log.Println("sm4 dec error: ", cErr)
		return
	}
	// log.Println("------------------------ Decrypt ", string(real))
	// testSM4()
	return saltStr, string(real), nil
}

// // PKCS7Padding adds padding to a block of plaintext.
// func PKCS7Padding(src []byte, blockSize int) []byte {
// 	padding := blockSize - len(src)%blockSize
// 	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
// 	return append(src, padtext...)
// }

// // PKCS7Unpadding removes padding from a block of ciphertext.
// func PKCS7Unpadding(src []byte) ([]byte, error) {
// 	length := len(src)
// 	unpadding := int(src[length-1])

// 	if unpadding > length || unpadding == 0 {
// 		return nil, fmt.Errorf("invalid padding")
// 	}

// 	for i := length - 1; i >= length-unpadding; i-- {
// 		if src[i] != byte(unpadding) {
// 			return nil, fmt.Errorf("invalid padding")
// 		}
// 	}

// 	return src[:length-unpadding], nil
// }

// func testSM4() {
// 	fmt.Println("\n====SM4 Test start ")
// 	key := []byte("1234567890abcdef")
// 	fmt.Printf("key = %v\n", key)
// 	data := []byte{0x01, 0x23, 0x45} //, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
// 	fmt.Printf("key = %v\n", key)
// 	fmt.Printf("data = %x\n", data)
// 	iv := []byte("0000000000000000")

// 	sm4.SetIV(iv)
// 	//sm4.Sm4GCM()
// 	//设置SM4算法实现的IV值,不设置则使用默认值
// 	ecbMsg, err := sm4.Sm4Ecb(key, data, true) //sm4Ecb模式pksc7填充加密
// 	if err != nil {
// 		fmt.Println("sm4 enc error: ", err)
// 		return
// 	}
// 	fmt.Printf("ecbMsg = %x\n", ecbMsg)
// 	ecbDec, err := sm4.Sm4Ecb(key, ecbMsg, false) //sm4Ecb模式pksc7填充解密
// 	if err != nil {
// 		fmt.Println("sm4 dec error: ", err)
// 		return
// 	}
// 	fmt.Printf("ecbDec = %x\n", ecbDec)
// 	fmt.Println("====SM4 Test End ")
// }
